package com.zshan.clinic.admin.util;


import com.zshan.clinic.admin.entity.vo.*;
import com.zshan.clinic.common.enums.VisitPeriodEnum;
import com.zshan.clinic.common.enums.YesOrNoEnum;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * 预约工具类
 * @author lichen
 */
@Slf4j
public class RegUtil {


    /**
     * 生成当前的唯一诊号
     * @param visitDate 就诊日期
     * @param doctorId 医生ID
     * @param period 就诊时段
     * @param seqNo 序号
     * @return 20250710000110001
     */
    public static String getVisitNo(LocalDate visitDate, Long clinicId,Long doctorId, String period, Integer seqNo) {
        String dateStr = visitDate.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String seqNoStr = String.format("%04d", seqNo);
        return dateStr + clinicId + doctorId + period + seqNoStr;
    }

    /**
     * 加载医生预约时段
     * 以【2025-10-22 晚上 18:00~23:59】为例
     */
    public static void buildPeriodList(LocalDate localDate, DoctorRemainVo doctorRemainVo) {
        // 当前时间，用来判断是否过期
        // 比如当前时间 = 2025-10-22 19:05
        LocalDateTime now = LocalDateTime.now();

        // 医生排班列表
        // 示例：只有一条夜班排班 [18:00~23:59]
        List<DoctorShiftRegVo> regList = doctorRemainVo.getRegList();

        // 每次接诊时长
        // 示例：visitTime = 10 分钟
        int visitTime = doctorRemainVo.getVisitTime();

        List<DoctorRegPeriodVo> periodList = new ArrayList<>();
        int remainCount = 0;

        for (VisitPeriodEnum period : VisitPeriodEnum.values()) {
            // periodStartDT = 2025-10-22T18:00
            // periodEndDT   = 2025-10-22T23:59
            LocalDateTime periodStartDT = LocalDateTime.of(localDate, period.getStartTime());
            LocalDateTime periodEndDT   = LocalDateTime.of(localDate, period.getEndTime());

            List<DoctorRegPeriodDetailVo> details = new ArrayList<>();

            for (DoctorShiftRegVo shift : regList) {
                // shiftStartDT = 2025-10-22T18:00
                // shiftEndDT   = 2025-10-22T23:59
                LocalDateTime shiftStartDT = LocalDateTime.of(localDate, shift.getStartTime());
                LocalDateTime shiftEndDT   = LocalDateTime.of(localDate, shift.getEndTime());

                // overlapStart = 18:00
                // overlapEnd   = 23:59
                LocalDateTime overlapStart = shiftStartDT.isAfter(periodStartDT) ? shiftStartDT : periodStartDT;
                LocalDateTime overlapEnd   = shiftEndDT.isBefore(periodEndDT)   ? shiftEndDT   : periodEndDT;
                if (!overlapStart.isBefore(overlapEnd)) {
                    continue;
                }

                // 已预约的记录（只筛本时段）
                // 假设已预约 18:30 这一段
                List<DoctorShiftRegDetailVo> bookedList = new ArrayList<>();
                if (shift.getDetailList() != null) {
                    for (DoctorShiftRegDetailVo d : shift.getDetailList()) {
                        if (period.getValue().equals(d.getVisitPeriod())) {
                            bookedList.add(d);
                        }
                    }
                }

                // 没有请假时段就不进入这段逻辑
                boolean hasLeave = YesOrNoEnum.YES.getValue().equals(shift.getIsLeave())
                        && shift.getLeaveStartTime() != null
                        && shift.getLeaveEndTime() != null;
                LocalDateTime leaveStartDT = null, leaveEndDT = null;
                if (hasLeave) {
                    leaveStartDT = LocalDateTime.of(localDate, shift.getLeaveStartTime());
                    leaveEndDT   = LocalDateTime.of(localDate, shift.getLeaveEndTime());
                }

                // 18:00~23:59 每10分钟一个片段
                // 第1个片段：18:00~18:10
                // 第2个片段：18:10~18:20
                // ...
                // 最后一个片段：23:40~23:50
                // 23:50~00:00 不会被生成，因为 00:00 > 23:59
                for (LocalDateTime t = overlapStart; !t.plusMinutes(visitTime).isAfter(overlapEnd); t = t.plusMinutes(visitTime)) {
                    LocalDateTime slotStartDT = t;
                    LocalDateTime slotEndDT   = t.plusMinutes(visitTime);

                    // 如果有请假，比如 20:00~20:30，
                    // 则 20:00-20:10、20:10-20:20、20:20-20:30 这几段会被过滤掉
                    if (hasLeave) {
                        boolean noOverlapWithLeave = slotEndDT.compareTo(leaveStartDT) <= 0 || slotStartDT.compareTo(leaveEndDT) >= 0;
                        if (!noOverlapWithLeave) {
                            continue;
                        }
                    }

                    // 判断是否已预约
                    // 若 bookedList 中有 18:30，则 18:30-18:40 这段 isBooked = true
                    boolean isBooked = false;
                    for (DoctorShiftRegDetailVo booked : bookedList) {
                        if (booked.getVisitStartTime() != null
                                && booked.getVisitStartTime().equals(slotStartDT.toLocalTime())) {
                            isBooked = true;
                            break;
                        }
                    }

                    // 判断是否过期
                    // 当前时间 19:05 时：
                    // 18:00~18:10 这段 slotStart=18:00 < now => 已过期
                    // 19:10~19:20 这段 slotStart=19:10 > now => 可预约
                    boolean isExpired = slotStartDT.isBefore(now);

                    DoctorRegPeriodDetailVo detail = new DoctorRegPeriodDetailVo();
                    detail.setStartTime(slotStartDT.toLocalTime()); // 18:00
                    detail.setEndTime(slotEndDT.toLocalTime());     // 18:10
                    detail.setShiftId(shift.getShiftId());
                    detail.setDeptId(shift.getDeptId());
                    detail.setRoomId(shift.getRoomId());
                    detail.setAvailable((!isBooked && !isExpired) ? YesOrNoEnum.YES.getValue() : YesOrNoEnum.NO.getValue());

                    details.add(detail);
                }
            }

            if (!details.isEmpty()) {
                // 排序并编号
                // 例如 18:00 对应 visitSeqNo = 1，18:10 对应 2 ...
                details.sort(Comparator.comparing(DoctorRegPeriodDetailVo::getStartTime));
                for (int i = 0; i < details.size(); i++) {
                    details.get(i).setVisitSeqNo(i + 1);
                }

                // 统计余号
                // 例如 50 个片段中，有 5 段已预约、20 段已过期，余号 = 25
                int remain = 0;
                for (DoctorRegPeriodDetailVo d : details) {
                    if (YesOrNoEnum.YES.getValue().equals(d.getAvailable())) {
                        remain++;
                    }
                }

                DoctorRegPeriodVo periodVo = new DoctorRegPeriodVo();
                periodVo.setValue(period.getValue());
                periodVo.setText(period.getText());
                periodVo.setStartTime(period.getStartTime());
                periodVo.setEndTime(period.getEndTime());
                periodVo.setDetailList(details);
                periodVo.setRemainCount(remain);

                remainCount += remain;
                periodList.add(periodVo);
            }
        }

        doctorRemainVo.setRemainCount(remainCount);
        doctorRemainVo.setPeriodList(periodList);
    }



}
